#pragma once

#include "device/Vector_dev.hpp"
#include "Ray.hpp"
#include "Intersection.hpp"
#include "Light.hpp"
#include "BVH.hpp"
#include "UnifiedMemManaged.hpp"

class Scene : public UnifiedMemManaged
{
#define MAX_OBJ_NUM 16
#define MAX_LIGHT_NUM 16
public:
    int width = 784, height = 784, fov = 40;
    // creating the scene (adding objects and lights)
    Object *objects[MAX_OBJ_NUM];
    int objects_num = 0;
    Light *lights[MAX_LIGHT_NUM];
    int lights_num = 0;
    const float RussianRoulette = 0.8F;
    const float EPSILON = 0.00001F;

    BVHAccel *bvh;

    Scene() {}

    __device__ Vector3fDev castRay(const Ray &ray, int depth, int thread_id) const;
    __device__ void sampleLight(Intersection &pos, float &pdf, int thread_id) const;
    __device__ bool trace(const Ray &ray, const Object *objects, const int objects_num, float &tNear, uint32_t &index, Object **hitObject) const;

    __device__ Intersection intersect(const Ray &ray) const;
    void buildBVH();

    void Add_object(Object *object)
    {
        assert(objects_num < MAX_OBJ_NUM);
        objects[objects_num++] = object;
    }

    void Add_light(Light *light)
    {
        assert(lights_num < MAX_LIGHT_NUM);
        lights[lights_num++] = light;
    }
};
